﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "GbmpCommandBase.h"
#include "GbmpUiPlatformCommandIds.h"
#include "GbmpUiPlatformCommandRegister.h"
#include "IApplication.h"
#include "IMainWindow.h"
#include "IDocument.h"
#include "CreatePlanViewDlg.h"
#include "ILevel.h"
#include "IGbmpPlanView.h"
#include "GbmpModelViewTypes.h"
#include "IModelView.h"
#include "IUserTransaction.h"
#include "CmdStatusUtils.h"
#include "UiDocumentViewUtils.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"
using namespace gcmp;

class CmdCreatePlanView :public GbmpCommandBase
{
public:
    CmdCreatePlanView():GbmpCommandBase(ID_CMD_GBMP_CREATE_PLAN_VIEW){}
    virtual ~CmdCreatePlanView() {}

public:
    virtual bool IsVisible() const override { CMD_ONLY_VISIBLE_IN_PROJECT_ENVIRONMENT; }
    virtual bool IsEnabled() const override { CMD_ONLY_VISIBLE_IN_PROJECT_ENVIRONMENT; }

public:
    virtual OwnerPtr<IAction> ExecuteCommand(const CommandParameters& cmdParams) override;

private:
    gcmp::IGbmpPlanView* CreatePlanView(gcmp::IDocument* pDoc,const ILevel *pLevel);
    //gcmp::IModelView* CreateCeilingView(gcmp::IDocument* pDoc, const ILevel *pLevel);
    std::wstring DeduceAvailableViewNameByLevelNameAndViewType(gcmp::IDocument* pDoc, const std::wstring& levelName, const std::wstring &viewType);

    /// \brif 提取名称中的索引，如“楼层1-02”中的“02”，返回2；
    /// \fullName 要被提取的名字，如“楼层1-01” 
    /// \partName 索引前的部分，如“楼层1”
    /// \separator 分隔符，如“-”
    /// \return 返回索引，fullName与partName相同返回0，获取失败（不存在包含关系、fullName中partName部分之后不为‘-’等，例如fullName:楼层10-01，partName:楼层1）返回-1
    int ExtractIndex(const std::wstring &fullName, const std::wstring &partName,const std::wstring &separator);
};

gcmp::OwnerPtr<gcmp::IAction> CmdCreatePlanView::ExecuteCommand(const CommandParameters& cmdParams)
{
    QWidget* pMainWindow = dynamic_cast<QWidget*>(IMainWindow::GetMainWindow());
    DBG_WARN_AND_RETURN_UNLESS(pMainWindow, nullptr, L"pMainWindow为空",L"GDMPLab",L"2024-03-30");
    gcmp::IDocument* pDoc = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_UNLESS(pDoc, nullptr, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    CreatePlanViewDlg dlg(pDoc,pMainWindow);
    dlg.InitDialog();
    if (QDialog::Accepted == dlg.exec())
    {
        const std::vector<const ILevel*> selectedItems = dlg.GetSelectedItemList();
        bool bCreatePlanView = dlg.WhetherCreatePlanView();
        //bool bCreatCeilingView = dlg.WhetherCreateCeilingView();

        if (bCreatePlanView)
        {
            FOR_EACH(item, selectedItems)
            {
                CreatePlanView(pDoc, item);
            }
        }
        //if (bCreatCeilingView)
        //{
        //    FOR_EACH(item, selectedItems)
        //    {
        //        CreateCeilingView(pDoc, item);
        //    }
        //}
    }
    return nullptr;
}

gcmp::IGbmpPlanView* CmdCreatePlanView::CreatePlanView(gcmp::IDocument* pDoc, const ILevel *pLevel)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pLevel, L"pLevel不合法",L"GDMPLab",L"2024-03-30");

    const std::wstring name = DeduceAvailableViewNameByLevelNameAndViewType(pDoc, pLevel->GetName(), PlanViewType);

    OwnerPtr<IUserTransaction> ut = IUserTransaction::Create(pDoc, L"创建平面视图");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(ut != nullptr, L"事务创建不成功",L"GDMPLab",L"2024-03-30");

    GbmpPlanViewInput input;
    input.Document = pDoc;
    input.Name = name;
    input.Level = const_cast<ILevel*>(pLevel);
    IGbmpPlanView* pPlanView = IGbmpPlanView::Create(input);
    ut->Commit();
    return pPlanView;
}

std::wstring CmdCreatePlanView::DeduceAvailableViewNameByLevelNameAndViewType(gcmp::IDocument* pDoc, const std::wstring& levelName, const std::wstring &viewType)
{
    std::wstring ret(L"");
    DBG_WARN_AND_RETURN_UNLESS(pDoc, ret, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    std::vector<IModelView*> vecOrginModelView = IModelView::GetAllModelViews(pDoc);
    std::set<int> usedModelViewNameIndexes;
    //获取所有 名字中包含了指定标高名字 的平面或者天花板视图 的Index
    FOR_EACH(pModelView, vecOrginModelView)
    {
        if (pModelView && viewType == pModelView->GetUserDataId())

        {
            std::wstring modelViewName = pModelView->GetName();
            int index = ExtractIndex(modelViewName, levelName, std::wstring(L"-"));
            if (index >= 0)
            {
                usedModelViewNameIndexes.insert(index);
            }
        }
    }

    if (usedModelViewNameIndexes.empty())
    {
        return levelName;
    }
    else
    {
        auto maxIndexIter = usedModelViewNameIndexes.rbegin();
        std::wstringstream wss;
        wss << std::setw(2) << std::setfill(L'0')<< StringUtil::ToWString((*maxIndexIter)+1);
        return levelName + std::wstring(L"-") + wss.str();
    }
}

int CmdCreatePlanView::ExtractIndex(const std::wstring &fullName, const std::wstring &partName, const std::wstring &separator)
{
    size_t fullNameSize = fullName.size();
    size_t partNameSize = partName.size();
    if (fullNameSize == 0 || partNameSize == 0)
        return -1;
    if (fullName == partName)
        return 0;
    if (fullNameSize > partNameSize + separator.size() &&
        fullName.find(partName + separator, 0) != std::string::npos)
    {
        std::wstring indexWString(fullName.begin() + partNameSize + separator.size(), fullName.end());
        indexWString = StringUtil::TrimSpace(indexWString);
        bool bOk = false;
        int index = StringUtil::ToNumber<int>(indexWString, &bOk);
        return bOk ? index : -1;
    }
    return -1;
}

REGISTER_GM_COMMAND(CmdCreatePlanView);
